import java.util.concurrent.locks.ReentrantLock;

/**
 * 死锁
 * Created by brss on 2018/3/25.
 */
public class DeadLock {

    private static Object locka = new Object();
    private static Object lockb = new Object();

    public static void main(String[] args) {
        new DeadLock().deadLock();
    }

    private void deadLock() {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (locka){
                    try {
                        System.out.println(Thread.currentThread().getName()+"获取A锁 ing!");
                        Thread.sleep(500);
                        System.out.println(Thread.currentThread().getName()+"睡眠了500ms");

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"需要B锁！！！");
                    synchronized (lockb){
                        System.out.println(Thread.currentThread().getName()+"B锁中");
                    }
                }
            }
        },"thread1");



        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lockb){
                    try {
                        System.out.println(Thread.currentThread().getName()+"获取B锁 ing!");
                        Thread.sleep(500);
                        System.out.println(Thread.currentThread().getName()+"睡眠了500ms");

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"需要A锁！！！");
                    synchronized (locka){
                        System.out.println(Thread.currentThread().getName()+"A锁中");
                    }
                }
            }
        },"thread2");


        thread1.start();
        thread2.start();
    }


}
/*
死锁可能出现的地方：哪里有并发，哪里就有可能有死锁。
嵌套锁，会出现死锁。
避免死锁的方法
    1.尽量不要写锁的嵌套
    2.在锁嵌套的情况下，按照同样的顺序进行锁嵌套。
    3.引入超时机制
        Lock接口 ： 显式锁 ，锁的时候调用lock，解锁的时候调用unlock
            它的实现类：ReentrantLock
        ReentrantReadWriteLock : 读写锁，如果你上了写锁，那么所有线程互斥，和synchronized差不多，如果上了读锁，那么多个线程是可以随便并发读，但不能写。
显示锁
中断锁
公平锁

数据库层面：
    乐观锁：不会阻止你读数据，如A读了一个字段，紧接着，B并发修改了这个字段，这时，A内存中的数据还是过期的，A由过期的数据运算后得到新的数据写回数据库时，就会引发问题。解决：加入version字段，A往回写时判断version还是不是和刚才读的时候一样，如果不一致，则提示写入失败即可。
    悲观锁：A读了这条数据，则在A释放这个锁之前，其他人无法读取这条数据。实现办法（SQL层面）:select * from user FOR UPDATE;意思是这条查询是为了更新数据而查询的，会阻塞其他查询。

    如果分库了，则在SQL层面悲观锁锁不住了，这时需要分布式锁（redis,zk等抢占一个资源）。

    ABA问题：乐观锁中增加的version字段，当前vserion为1，第一个线程拿到version是1，第二个线程来了把version修改为2，第三个线程来了把version修改为1，这时，第一个线程运算完成，打算往数据库写，和数据库比对之后发现version还是1，就放心的写入了，其实，这时的1其实已经不是它读到的1了，所以就会产生问题。解决办法：板子version字段是不会重复的或者递增的。
*/
